Skip to content

Add @conditions, smithy-model-jmespath, NodeValidationPlugin SPI#2935

Merged
kstich merged 18 commits intosmithy-lang:mainfrom
robin-aws:smithy-contracts-squashed
Feb 2, 2026
Merged

Add @conditions, smithy-model-jmespath, NodeValidationPlugin SPI#2935
kstich merged 18 commits intosmithy-lang:mainfrom
robin-aws:smithy-contracts-squashed

Conversation

@robin-aws
Copy link
Contributor

@robin-aws robin-aws commented Jan 20, 2026

Background

  • What do these changes do?
    • The main contribution is @conditions, the first "contract trait", which specifies JMESPath expressions that must evaluate to true.
    • To support this:
      • Adds smithy-model-jmespath, to contain a JmespathRuntime<T> adaptor for Node values.
      • Adds an SPI for NodeValidatorPlugin so that packages outside of smithy-model can provide additional node validation.
      • Optimizes NodeValidationVisitor to index NodeValidatorPlugins by ShapeType, to improve on the current approach that invokes all 10 existing plugins for every node regardless of type.
      • Moved the two existing copies of ModelRuntimeTypeGenerator and tests into smithy-model-jmespath, to avoid having to define a third copy.
  • Why are they important?
    • This trait helps both humans and LLMs understand correct use of APIs better, especially constraints that are already manually checked in a service but not otherwise encoded/documented in the model. We reviewed an internal design doc on this that I could add to this PR if desired.

Testing

  • How did you test these changes?
    • Existing NodeValidationVisitor tests for the optimization.
    • New tests in smithy-model-jmespath and smithy-contracts

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@robin-aws robin-aws requested a review from a team as a code owner January 20, 2026 04:18
@robin-aws robin-aws requested a review from kstich January 20, 2026 04:18
@github-actions
Copy link
Contributor

This pull request does not contain a staged changelog entry. To create one, use the ./.changes/new-change command. For example:

./.changes/new-change --pull-requests "#2935" --type feature --description "Add @conditions, smithy-model-jmespath, NodeValidationPlugin SPI"

Make sure that the description is appropriate for a changelog entry and that the proper feature type is used. See ./.changes/README or run ./.changes/new-change -h for more information.

@yasmewad yasmewad requested a review from mtdowling January 23, 2026 17:33
Comment on lines 47 to 48
private List<
ValidationEvent> validateCondition(Model model, Shape shape, String conditionName, Condition condition) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did the code formatter really do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It did! I put the parameters on separate lines and that avoided it.

robin-aws and others added 4 commits January 29, 2026 07:35
…ntracts/Condition.java

Co-authored-by: Kevin Stich <kevin@kstich.com>
…ntracts/Condition.java

Co-authored-by: Kevin Stich <kevin@kstich.com>
import software.amazon.smithy.model.traits.Trait;

abstract class MemberAndShapeTraitPlugin<S extends Shape, N extends Node, T extends Trait>
public abstract class MemberAndShapeTraitPlugin<N extends Node, T extends Trait>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be public for this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's beneficial because ConditionsTraitPlugin extends it, and doesn't live in smithy-model. I'd expect most plugins to be based on some trait so most will also want to extend this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh but it needs Javadoc in that case, so I added that.

* @return A {@link BiPredicate} that returns true if this plugin
* has an effect on Node values of the given shape.
*/
default BiPredicate<Model, Shape> shapeMatcher() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You made a ShapeTypeFilter plugin. Why not replace this method with ShapeTypeFilter getFilter()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was intending to leave the door open to optimize further in the future, indexing by individual shape rather than just shape type. With this signature plugins can filter more precisely if they want.

I could make the return type ShapeTypeFilter for now, since I could replace that with a supertype later without breaking folks. But I wouldn't want to make the name more specific since I can't change that later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or rather if I make it getFilter() now, I might end having to add a default BiPredicate<Model, Shape> shapeMatcher() method later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline and the opportunity cost is just not that high realistically, so I made the change. :)

@kstich kstich merged commit 9fa0f35 into smithy-lang:main Feb 2, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants